/**
 * Author shuqi
 * Rev
 * Date: 2019-12-10 17:56
 * <p>
 * Copyright (C) 2019 Seeyon, Inc. All rights reserved.
 * <p>
 * This software is the proprietary information of Seeyon, Inc.
 * Use is subject to license terms.
 * @company seeyon.com
 * @since V5 V8.0
 * @author shuqi
 */
package com.shuqi.tools.actions;

import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DataKeys;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.shuqi.tools.CMPHelper;
import com.shuqi.tools.dto.BuildConfig;
import com.shuqi.tools.dto.Manifest;
import com.shuqi.tools.utils.Constants;
import com.shuqi.tools.utils.LoggerUtils;
import com.shuqi.tools.utils.NotifyUtils;
import com.shuqi.tools.utils.SyncUtils;
import com.shuqi.utils.JSONUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.InputStream;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @description
 * @date 2019-12-10 17:56
 * @since V5 V8.0
 * @author shuqi
 */
public abstract class AbsBuildAction<javaExe> extends AnAction {
	private static Set<String> excludleFileName = new HashSet<>(Arrays.asList(
			".idea",
			".project"
	));

	private AtomicBoolean runing = new AtomicBoolean(false);
	/**
	 * 获取构建类型
	 * @return
	 * @date	2019-12-10 18:03:32
	 * @since	V5 V8.0
	 * @author  shuqi
	 */
	public abstract Constants.BuildType buildType();

	private static String javaExeTpl = "%s" + File.separator + "jdk" + File.separator + "bin" + File.separator + "java.exe";
	private static String jarPathTpl = "{0}/libs/fastjson-1.1.27.jar;{0}/libs/s3script.jar;{0}/libs/rhino_15.jar";

	@Override
	public void actionPerformed(AnActionEvent event) {
		if(runing.get()){
			NotifyUtils.info("正在打包，请稍后。。。",event.getProject());
			return;
		}
		Pair<Boolean, String> data = canShow(event);
		if(!data.getLeft()){
			return;
		}
		BuildConfig config = CMPHelper.getHelper(event.getProject()).getConfig();
		if(!config.isOK()){
			NotifyUtils.error("请配置再使用：File -> Settings -> Tools -> CMP Helper Config",event.getProject());
			return;
		}
		runing.set(true);
		new Thread(()->{
			try {
				NotifyUtils.info("开始打包，请稍后。。。",event.getProject());
				Long start = System.currentTimeMillis();
				LoggerUtils.info("start build app");

				// 读取manifest.json
				String mateJson = FileUtils.readFileToString(new File(String.format(Constants.manifestPath,data.getRight())), "utf-8");
				Manifest mateMap = JSONUtils.parseJson(mateJson, Manifest.class);

				File rootAppPath = new File(data.getRight());
				String tmpdir = System.getProperty("java.io.tmpdir");
				String uuid = "cmp_pack_" + Calendar.getInstance().getTimeInMillis();
				File targetDir = new File(tmpdir, uuid);
				targetDir.mkdirs();

				FileUtils.copyDirectory(rootAppPath, targetDir, new FileFilter() {
					@Override
					public boolean accept(File pathname) {
						if(excludleFileName.contains(pathname.getName())){
							return false;
						}
						return true;
					}
				});


				// 处理国际化
				File i18nFilePath = new File(rootAppPath,"i18n");
				for (File file : i18nFilePath.listFiles()) {
					File targetJS = new File(targetDir.getCanonicalPath() + File.separator + "i18n",file.getName().replaceAll("\\.properties", "\\.js"));
					SyncUtils.covertPropToJS(file,targetJS);
					file.delete();
				}
				if (StringUtils.isBlank(config.getM3ToolsPath())){
					NotifyUtils.error("请配置m3_tools目录：File -> Settings -> Tools -> CMP Helper Config",event.getProject());
					return;
				}


				// ${m3Tools}/jdk/bin/java.exe
				String javaExe = String.format(javaExeTpl, config.getM3ToolsPath());
				String jarPath = MessageFormat.format(jarPathTpl, config.getM3ToolsPath().replaceAll("\\\\","/"));
				File outZip = new File(targetDir.getCanonicalPath()+".zip");
				String dataFilePath = null;



				if(buildType().equals(Constants.BuildType.CMP)){
					dataFilePath = String.format(Constants.cmpDataPath, rootAppPath.getAbsolutePath());
				}else {
					dataFilePath = String.format(Constants.wechatDataPath, rootAppPath.getAbsolutePath());
				}
				String cmd = javaExe + " -Dfile.encoding=UTF-8  -classpath " + jarPath + " org.s3.script.web.S3ScriptPublishCmd -sourcepath " + targetDir.getAbsolutePath() + "  -outfile " + outZip.getAbsolutePath() +
						" -commondata " + dataFilePath + " -testdatapath null  -noexportpaths 'appRes;WEB-INF;s3scriptjspdata;s3uuid.data'  -buildversion true";
				LoggerUtils.info("cmd : " + cmd);
				Process p = Runtime.getRuntime().exec(cmd);

				InputStream is1 = p.getInputStream();
				new Thread(()->{
					try {
						IOUtils.copy(is1,System.out);
					} catch (IOException e) {
						LoggerUtils.error("", e);
					}finally {
						IOUtils.closeQuietly(is1);
					}
				}).start(); // 启动单独的线程来清空p.getInputStream()的缓冲区
				InputStream error = p.getErrorStream();
				IOUtils.copy(error,System.err);
				p.waitFor();
				this.afterPack(mateMap,config,outZip,event.getProject());
				outZip.delete();
				FileUtils.deleteQuietly(targetDir);

				LoggerUtils.info("build app finished ," + (System.currentTimeMillis()  - start ) + " ms");
				if(buildType().equals(Constants.BuildType.CMP)){
					NotifyUtils.info("打包完成！",event.getProject());
				}else{
					NotifyUtils.info("打包完成！",event.getProject());
				}
			} catch (Exception e) {
				NotifyUtils.error("打包出错了 ： " + e.getLocalizedMessage(),event.getProject());
				LoggerUtils.error("打包出错了", e);
			}finally {
				runing.set(false);
			}
		}).start();
	}

	protected abstract void afterPack(Manifest mateMap, BuildConfig config, File outZip, Project project);
	//	@Override
//	public void beforeActionPerformedUpdate(@NotNull AnActionEvent e) {
//		Pair<Boolean, String> rs = canShow(e);
//		this.getTemplatePresentation().setVisible(rs.getLeft());
//	}
//	@Override
//	public void update(@NotNull AnActionEvent e) {
//		this.beforeActionPerformedUpdate(e);
//	}
	/**
	 * 判断是否为m3目录
	 * @param event
	 * @return
	 */
	protected static Pair<Boolean,String> canShow(AnActionEvent event) {
		VirtualFile file = PlatformDataKeys.VIRTUAL_FILE.getData(event.getDataContext());
		String path = file.getCanonicalPath();
		String mateInfoPath  = String.format(Constants.manifestPath,path);
		if(new File(mateInfoPath).exists()){
			return Pair.of(true,path);
		}
		return Pair.of(false,null);
	}
}
